"""
All of these models are based on the shape files from the City of 
Chicago found here:

http://egov.cityofchicago.org/city/webportal/portalContentItemAction.do?BV_SessionID=@@@@1577922727.1230492862@@@@&BV_EngineID=ccceadegdhimekfcefecelldffhdfho.0&contentOID=536900083&contenTypeName=COC_EDITORIAL&topChannelName=SubAgency&blockName=Geographic+Information+Systems%2FGIS+Data%2FI+Want+To&context=dept&channelId=0&programId=0&entityName=Geographic+Information+Systems&deptMainCategoryOID=-536886491

Requires the aggregtor module from the Django website source code.
"""

import datetime, re
from django.contrib.gis.db import models
from django.contrib.gis import admin
from django.contrib.localflavor.us.models import PhoneNumberField
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.db.models import signals  
from django.contrib.sites.models import Site
from django.template.loader import render_to_string
from django.core.urlresolvers import reverse
from django.conf import settings
from chicago.signals import *
from aggregator.models import Feed

SHA1_RE = re.compile('^[a-f0-9]{40}$')
CONFIRM_EXPIRES = 30 #days

class Rep(models.Model):

    first_name = models.CharField(max_length=50)
    middle_name = models.CharField(max_length=50, blank=True)
    last_name = models.CharField(max_length=100)
    slug = models.SlugField()
    bio = models.TextField(blank=True)
    address = models.CharField(max_length=120,blank=True)
    telephone = PhoneNumberField(blank=True)
    feeds = generic.GenericRelation('FeedMap')


    def __unicode__(self):
        return "%s %s %s" % (
                self.first_name, 
                self.middle_name, 
                self.last_name)

    def get_regions(self):
        """Yuck.  Linking up relations for admin."""
        regions = []

        for ward in self.ward_set.all():
            regions.append('<a href="/admin/chicago/ward/%s">%s</a>' %  (ward.id, ward))
        for house in self.house_set.all():
            regions.append('<a href="/admin/chicago/house/%s">%s</a>' %  (house.id, house))
        for senate in self.senate_set.all():
            regions.append('<a href="/admin/chicago/senate/%s">%s</a>' %  (senate.id, senate))
        for congress in self.congress_set.all():
            regions.append('<a href="/admin/chicago/congress/%s">%s</a>' %  (congress.id, congress))

        return ', '.join(regions)

    get_regions.allow_tags = True

    def get_feeds(self):
        links = []
        for f in self.feeds.all():
            links.append(
                '<a href="/admin/aggregator/feeditem/?feed__id__exact=%s">%s</a> (%s)' % (f.feed.id,f.feed,len(f.feed.feeditem_set.all())))
        return ', '.join(links)

    get_feeds.allow_tags = True

    def google_feed_url(self):
        query_str = str(self)
        return 'http://news.google.com/news?q="%s"&ie=UTF-8&nolr=1&output=rss' % query_str.replace(' ','+')

    def google_public_url(self):
        query_str = str(self)
        return 'http://news.google.com/news?q="%s"&ie=UTF-8&nolr=1' % query_str.replace(' ','+')

        #return 'http://news.search.yahoo.com/news/rss?p=%s+chicago&ei=UTF-8' % query_string.replace(' ','+')
        #return 'http://news.google.com/news?ned=us&topic=h&output=rss'

    class Meta:
        ordering = ('last_name',)

class FeedMap(models.Model):
    """Map any object to one or more feeds.  
    We're just maintaining feeds on Reps right now.  Feeds are unique in the 
    feeds table, so duplicate feeds won't get saved.  But more than one object
    can use the same feed. Ok, a bit of design.
    """
    feed = models.ForeignKey(Feed)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    object = generic.GenericForeignKey()

    def __unicode__(self):
        return str(self.object)

# setup signal to update feedmap when a rep is created
signals.post_save.connect(update_feeds, sender=Rep)
signals.pre_delete.connect(del_feeds, sender=Rep)

class Ward(models.Model):

    perimeter = models.FloatField()
    ward = models.IntegerField()
    alderman = models.CharField(max_length=50)
    rep = models.ForeignKey(Rep, null=True)
    ward_phone = models.CharField(max_length=12,blank=True)
    hall_phone = models.CharField(max_length=12,blank=True)
    office_address = models.CharField(max_length=120)
    address = models.CharField(max_length=120)
    # in illinois 83 east ft 
    # http://spatialreference.org/ref/epsg/3435/
    area = models.GeometryField(srid=3435) 
    #area = models.MultiPolygonField(srid=3435) 
    shape_area = models.FloatField()
    shape_length = models.FloatField()

    objects = models.GeoManager()

    def __unicode__(self):
        return "City Ward %s" % self.ward


class House(models.Model):

    PARTY_CHOICES = (
        ('D','Democrat'),
        ('R','Republican'),
    )

    perimeter = models.FloatField()
    new_ilhouse = models.IntegerField()
    new_ilhouse1 = models.IntegerField()
    name = models.CharField(max_length=100)
    rep = models.ForeignKey(Rep, null=True)
    party = models.CharField(max_length=1, choices=PARTY_CHOICES)
    district = models.CharField(max_length=50)
    address = models.CharField(max_length=120,blank=True)
    telephone = models.CharField(max_length=15,blank=True)
    # in illinois 83 east ft 
    # http://spatialreference.org/ref/epsg/3435/
    area = models.PolygonField(srid=3435) 
    shape_area = models.FloatField()
    shape_length = models.FloatField()

    objects = models.GeoManager()

    def __unicode__(self):
        return "State House District %s" % self.district

class Senate(models.Model):
    """
    http://egov.cityofchicago.org/webportal/COCWebPortal/COC_ATTACH/IL_SENATE.zip
    """

    PARTY_CHOICES = (
        ('D','Democrat'),
        ('R','Republican'),
    )

    perimeter = models.FloatField()
    senate = models.IntegerField()
    senate_id = models.IntegerField()
    name = models.CharField(max_length=100)
    rep = models.ForeignKey(Rep, null=True)
    party = models.CharField(max_length=1, choices=PARTY_CHOICES)
    telephone = models.CharField(max_length=15,blank=True)
    address = models.CharField(max_length=120,blank=True)
    district = models.CharField(max_length=50)
    # in illinois 83 east ft 
    # http://spatialreference.org/ref/epsg/3435/
    area = models.MultiPolygonField(srid=3435) 
    shape_area = models.FloatField()
    shape_length = models.FloatField()

    objects = models.GeoManager()

    def __unicode__(self):
        return "State Senate District %s" % self.district

#Not needed ATM
#class TIFS(models.Model):
#    """
#    http://egov.cityofchicago.org/webportal/COCWebPortal/COC_ATTACH/TIFS2008.zip
#    """
#
#    name = models.CharField(max_length='100')
#    name_trim = models.CharField(max_length='100')
#    ref = models.CharField(max_length='10')
#    ind = models.CharField(max_length='50')
#    type = models.CharField(max_length='50')
#    use = models.CharField(max_length='100')
#    show = models.IntegerField(max_length='1')
#    area = models.PolygonField(srid=3435) 
#
#    objects = models.GeoManager()
#
#    def __unicode__(self):
#        return "TIF %s" % self.name
#
#class TIFSAdmin(admin.OSMGeoAdmin):
#    pass
# 
#admin.site.register(TIFS, TIFSAdmin)

class Congress(models.Model):

    """
    http://egov.cityofchicago.org/webportal/COCWebPortal/COC_ATTACH/US_Congress.zip
    """
    uscong = models.IntegerField(max_length=1)
    name = models.CharField(max_length=100)
    rep = models.ForeignKey(Rep, null=True)
    address = models.CharField(max_length=120,blank=True)
    telephone = PhoneNumberField(blank=True)
    district = models.CharField(max_length=3)
    area = models.PolygonField(srid=3435) 

    objects = models.GeoManager()

    def __unicode__(self):
        return "Congressional District %s" % self.district

    class Meta:
        verbose_name_plural = 'Congress'


class SubscriptionManager(models.GeoManager):


    def active(self):
        return self.filter(remove=False, confirmed=True)

    def confirm_sub(self, key):
        """Check if the confirmation key is correct, return a subscription
        object if so.  Otherwise return False.
        """
        if SHA1_RE.search(key):
            try:
                sub = self.get(confirm_key=key)
            except self.model.DoesNotExist:
                return False
            expires = datetime.timedelta(days=CONFIRM_EXPIRES)
            if not sub.created + expires <= datetime.datetime.now():
                sub.confirmed = True
                sub.save()
                return sub
        return False

class Subscription(models.Model):
    """Maintain a list of email addresses and reps to send mail to.
    """

    email = models.EmailField(db_index=True)
    ward = models.ForeignKey(Ward)
    house = models.ForeignKey(House)
    senate = models.ForeignKey(Senate)
    congress = models.ForeignKey(Congress)
    point  = models.PointField()
    place = models.CharField(max_length=150,db_index=True)
    feed = models.CharField(max_length=150,db_index=True)
    remove = models.BooleanField(default=False,db_index=True)
    created = models.DateTimeField(auto_now_add=True)
    confirmed = models.BooleanField(default=False,db_index=True)
    confirm_key = models.CharField(max_length=40)
    objects = SubscriptionManager()

    def __unicode__(self):
        return self.email

    def get_reps(self):
        """Return list of current reps for this subscriber."""

        return [self.ward.rep, 
                self.congress.rep, 
                self.house.rep, 
                self.senate.rep]

    class Meta:
        unique_together = (("email", "feed"),)
